package fun.ltool.core.excel;

import fun.ltool.core.excel.annotation.ExcelEntity;
import fun.ltool.core.excel.annotation.ExcelField;
import fun.ltool.core.excel.enums.DataTypeEnum;
import fun.ltool.core.excel.handler.ExcelDataRowHandler;
import fun.ltool.core.excel.handler.ExcelDataTableHandler;
import fun.ltool.core.exceptions.ExcelException;
import fun.ltool.core.reflect.ReflectUtil;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * Excel 数据映射类
 * <p>本工具不处理读取Excel 有很多其他优秀的工具类可以处理了比如 apache POI、二次处理的Hutool等</p>
 *
 * @author huangrongsong
 * @since 1.3
 */
public class ExcelDataMapping {
    /**
     * 加载数据 数据行模式{@link fun.ltool.core.excel.enums.DataTypeEnum#DATA_ROW_MODE}
     *
     * @param data              表格完整数据包含表头字段
     * @param excelMappingClass 映射实体类型
     * @param <D>               实体泛型
     * @return Excel数据处理类
     */
    public static <D> ExcelDataRowHandler<D> buildRowData(List<List<Object>> data, Class<D> excelMappingClass) {
        if (data == null || data.isEmpty() || excelMappingClass == null) {
            throw new ExcelException("数据和映射实体泛型不能为空，请检查");
        }
        ExcelEntity excelEntity = excelMappingClass.getAnnotation(ExcelEntity.class);
        // 判断是否有对应注解
        if (excelEntity == null) {
            throw new ExcelException("实体没有找到 @ExcelEntity注解请检查该实体：" + excelMappingClass.getName());
        }
        // 映射数据类型
        DataTypeEnum dataTypeEnum = excelEntity.dataType();
        // 获取包含ExcelField注解的Field
        Field[] fields = Arrays.stream(ReflectUtil.buildClass(excelMappingClass).getFields()).filter(field -> field.isAnnotationPresent(ExcelField.class)).toArray(Field[]::new);
        // 数据行模式
        if (dataTypeEnum != DataTypeEnum.DATA_ROW_MODE) {
            throw new ExcelException("请检查 @ExcelEntity注解属性dataType是否配置数据行模式");
        }
        return new ExcelDataRowHandler<>(data, excelMappingClass, excelEntity, fields);
    }

    /**
     * 加载数据 数据表模式{@link fun.ltool.core.excel.enums.DataTypeEnum#DATA_TABLE_MODE}
     *
     * @param data              表格完整数据包含表头字段
     * @param excelMappingClass 映射实体类型
     * @param <D>               实体泛型
     * @return Excel数据处理类
     */
    public static <D> ExcelDataTableHandler<D> buildTableData(List<List<Object>> data, Class<D> excelMappingClass) {
        if (data == null || data.isEmpty() || excelMappingClass == null) {
            throw new ExcelException("数据和映射实体泛型不能为空，请检查");
        }
        ExcelEntity excelEntity = excelMappingClass.getAnnotation(ExcelEntity.class);
        // 判断是否有对应注解
        if (excelEntity == null) {
            throw new ExcelException("实体没有找到 @ExcelEntity注解请检查该实体：" + excelMappingClass.getName());
        }
        // 映射数据类型
        DataTypeEnum dataTypeEnum = excelEntity.dataType();
        // 获取包含ExcelField注解的Field
        Field[] fields = Arrays.stream(ReflectUtil.buildClass(excelMappingClass).getFields()).filter(field -> field.isAnnotationPresent(ExcelField.class)).toArray(Field[]::new);
        // 数据表模式
        if (dataTypeEnum != DataTypeEnum.DATA_TABLE_MODE) {
            throw new ExcelException("请检查 @ExcelEntity注解属性dataType是否配置数据表模式");
        }
        return new ExcelDataTableHandler<>(data, excelMappingClass, excelEntity, fields);
    }
}
